﻿#include "ElementsReader.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QFile>
#include <QJsonDocument>
#include <qicon.h>
#include "ElementtreeItem.h"
#include <qtcsv/reader.h>
#include <qtcsv/writer.h>
#include <QXlsxQt6/xlsxdocument.h>
const QRegularExpression ElementsReader::mRegExpText("[\\s\\t]+");
const QRegularExpression ElementsReader::mRegExpCSV(",[\\s\\t]+");

struct PSModelOutData:public QtCSV::Reader::AbstractProcessor{
public:
    void preProcessRawLine(QString& editable_line)override
    {
        if(isPSMosel)
        {
            while(editable_line.endsWith(" ")){
                editable_line.removeLast();
            }
            while(editable_line.startsWith(" ")){
                editable_line.removeFirst();
            }
            auto index = editable_line.indexOf(' ',0);
            while(editable_line[index+1]==' '){
                editable_line.remove(index,1);
            }
        }
    }

    bool processRowElements(const QList<QString>& elements)override{
        m_data<<elements;
        return true;
    }
    QList<QStringList>& data(){
        return m_data;
    }
    void setIsPSMosel(bool isPSMosel){
        this->isPSMosel = isPSMosel;
    }
private:
    QList<QStringList> m_data;
    bool isPSMosel = true;
};
ElementsReader::ElementsReader() {}
/*
    DisplayRole = 0,// 显示的文字
    DecorationRole = 1,// 图标
    EditRole = 2, //
    ToolTipRole = 3, // 提示
    StatusTipRole = 4, // 状态栏信息
    WhatsThisRole = 5,
    // Metadata
    FontRole = 6, // 显示的文字字体
    TextAlignmentRole = 7, // 显示的文字对其方式
    BackgroundRole = 8,// 背景
*/
#include <QFileInfo>
#include<QMessageBox>
ElementTreeItem *ElementsReader::read(const QString &filePath) const
{
    QFileInfo fileInfo=QFileInfo(filePath);
    QString suffix=fileInfo.suffix();
    if(suffix=="xlsx"){
        return readExecl(filePath);
    }
    bool isPSMosel = true;
    if(suffix=="out"){
        suffix=" ";
    }
    else if(suffix=="csv"){
        isPSMosel = false;
        suffix=",";
    }else{
        return nullptr;
    }
    return readCSV(filePath,suffix,isPSMosel);
}

ElementTreeItem *ElementsReader::readCSV(const QString &filePath, const QString &sep,bool isPSMosel) const
{
    PSModelOutData data_;
    data_.setIsPSMosel(isPSMosel);
    try
    {
        bool ret=QtCSV::Reader::readToProcessor(filePath,data_,sep);
        if(!ret){
            return nullptr;
        }
    }
    catch(const std::exception& e)
    {
        QMessageBox::critical(nullptr,"Error",e.what());
        return nullptr;
    }
    QList<QStringList>& data = data_.data();
    // 获取表头
    QStringList headers = data.takeFirst();
    // 找到指定列的索引
    ElementTreeItem *pFirstItem = new ElementTreeItem();
    pFirstItem->setValue(Qt::DisplayRole,filePath);
    pFirstItem->setValue(ElementTreeItem::TimeName,headers[0]);
    // 时间
    for (const QStringList& row : data) {
        bool ok;
        double value = row[0].toDouble(&ok);
        if (ok) {
            pFirstItem->appendData(value);
        } else {
            delete pFirstItem;
            return nullptr;
        }
    }
    auto treeItemList = QList<ElementTreeItem *>(headers.size()-1);
    for(int i =1;i<headers.size();++i){
        auto& item = treeItemList[i-1];
        item = new ElementTreeItem();
        pFirstItem->appendChild(item);
        item->setValue(Qt::DisplayRole,headers[i]);
    }
    for (int i=0;i<data.count();++i) {
        const QStringList&row=data[i];
        for(int j=1;j<headers.count();++j){
            bool ok;
            auto& item = treeItemList[j-1];
            double value = row[j].toDouble(&ok);
            if (ok) {
                item->appendData(value);
            } else {
                delete pFirstItem;
                return nullptr;
            }
        }
    }
    return pFirstItem;
}


/*
CELLTYPE_EMPTY	empty, the cell doesn't exist
CELLTYPE_NUMBER	number value
CELLTYPE_STRING	string value
CELLTYPE_BOOLEAN	boolean value
CELLTYPE_BLANK	blank, the cell contains only format information
CELLTYPE_ERROR	error
*/
ElementTreeItem *ElementsReader::readExecl(const QString &filePath,FileType type) const
{
    // 打开现有的Excel文件
    QXlsx::Document xlsx(filePath);
    // 检查文件是否打开成功
    if (!xlsx.load()) {
        qDebug() << "Failed to load file.";
        return nullptr;
    }
    // 获取工作表的维度
    QXlsx::CellRange range = xlsx.dimension();
    int rowCount = range.rowCount();
    int colCount = range.columnCount();
    if(rowCount==0||colCount==0){
        qDebug()<<"No data in the file.";
        return nullptr;
    }
    ElementTreeItem *pFirstItem = new ElementTreeItem();
    QStringList headers=QStringList(colCount);
    for (int i = 1; i <= colCount; i++)
    {
        headers[i-1] = xlsx.read(1,i).toString();
    }
    pFirstItem->setValue(Qt::DisplayRole,filePath);
    pFirstItem->setValue(ElementTreeItem::TimeName,headers[0]);
    auto treeItemList = QList<ElementTreeItem *>(headers.size());
    treeItemList[0]=pFirstItem;
    for(int i =1;i<headers.size();++i){
        auto& item = treeItemList[i];
        item = new ElementTreeItem();
        pFirstItem->appendChild(item);
        item->setValue(Qt::DisplayRole,headers[i]);
    }
    for(int i=2;i<=rowCount;++i){
        for(int j=1;j<=colCount;++j){
            auto& item = treeItemList[j-1];
            item->appendData(xlsx.read(i,j).toDouble());
        }
    }
    return pFirstItem;
}
